///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
*	Contains a handy indexed triangle class.
*	\file		LaborIndexedTriangle.h
*	\author		Pierre Terdiman
*	\date		January, 17, 2000
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __LABORINDEXEDTRIANGLE_H__
#define __LABORINDEXEDTRIANGLE_H__
#include "../LaborCoreDef.h"
#include "../Math/LaborMathDecl.h"
NAMESPACE_LABOR3D_BEGIN
// Forward declarations
#ifdef _MSC_VER
enum CubeIndex;
#else
typedef int CubeIndex;
#endif

// An indexed triangle class.
class  LABORCORE_API CLIndexedTriangle
{
public:
	//! Constructor
	inline					CLIndexedTriangle()									{}
	//! Constructor
	inline					CLIndexedTriangle(unsigned int r0, unsigned int r1, unsigned int r2)	{ mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; }
	//! Copy constructor
	inline					CLIndexedTriangle(const CLIndexedTriangle& triangle)
	{
		mVRef[0] = triangle.mVRef[0];
		mVRef[1] = triangle.mVRef[1];
		mVRef[2] = triangle.mVRef[2];
	}
	//! Destructor
	inline					~CLIndexedTriangle()									{}
	//! Vertex-references
	unsigned int			mVRef[3];

	// Methods
	void			flip();
	float			area(const CLPoint3* verts)											const;
	float			perimeter(const CLPoint3* verts)										const;
	float			compacity(const CLPoint3* verts)										const;
	void			normal(const CLPoint3* verts, CLPoint3& normal)							const;
	void			denormalizedNormal(const CLPoint3* verts, CLPoint3& normal)				const;
	void			center(const CLPoint3* verts, CLPoint3& center)							const;
	void			centeredNormal(const CLPoint3* verts, CLPoint3& normal)					const;
	void			randomPoint(const CLPoint3* verts, CLPoint3& random)					const;
	bool			isVisible(const CLPoint3* verts, const CLPoint3& source)				const;
	bool			backfaceCulling(const CLPoint3* verts, const CLPoint3& source)			const;
	float			computeOcclusionPotential(const CLPoint3* verts, const CLPoint3& view)	const;
	bool			replaceVertex(unsigned int oldref, unsigned int newref);
	bool			isDegenerate()														const;
	bool			hasVertex(unsigned int ref)													const;
	bool			hasVertex(unsigned int ref, unsigned int* index)									const;
	unsigned char			findEdge(unsigned int vref0, unsigned int vref1)									const;
	unsigned int			oppositeVertex(unsigned int vref0, unsigned int vref1)								const;
	inline	unsigned int			oppositeVertex(unsigned char edgenb)											const	{ return mVRef[2-edgenb];	}
	void			getVRefs(unsigned char edgenb, unsigned int& vref0, unsigned int& vref1, unsigned int& vref2)		const;
	float			minEdgeLength(const CLPoint3* verts)									const;
	float			maxEdgeLength(const CLPoint3* verts)									const;
	void			computePoint(const CLPoint3* verts, float u, float v, CLPoint3& pt, unsigned int* nearvtx=NULL)	const;
	float			angle(const CLIndexedTriangle& tri, const CLPoint3* verts)				const;
	inline	CLPlane			planeEquation(const CLPoint3* verts)									const	{ return CLPlane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);	}
	bool			equal(const CLIndexedTriangle& tri)									const;
	CubeIndex		computeCubeIndex(const CLPoint3* verts)								const;

};

NAMESPACE_LABOR3D_END

#endif // __LABORINDEXEDTRIANGLE_H__
